package com.zjuh.goodboy.scheduler;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.impl.StdSchedulerFactory;

import com.zjuh.goodboy.awires.AppContextAwire;
import com.zjuh.goodboy.context.AppContext;
import com.zjuh.goodboy.util.DropOffLinkedBlockingQueue;


public class QuartzSchedulerService implements SchedulerService, AppContextAwire {

	private ExecutorService executorService;
	
	private List<SchedulerJob> schedulerJobs = new ArrayList<SchedulerJob>();
	
	private Scheduler scheduler;
	
	private AppContext appContext;
	
	private static final int MAX_QUEQUE_SIZE = 100;
	
	public void addSchedulerJob(SchedulerJob schedulerJob) {
		schedulerJobs.add(schedulerJob);
	}
	
	
	@Override
	public void setAppContext(AppContext appContext) {
		this.appContext = appContext;
	}

	@Override
	public synchronized void init() {
		try {
			int nThreads = Runtime.getRuntime().availableProcessors() + 1;
			executorService = new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new DropOffLinkedBlockingQueue<Runnable>(MAX_QUEQUE_SIZE));
			
			int index = 1;
			scheduler = StdSchedulerFactory.getDefaultScheduler();
			scheduler.getContext().put("appContext", appContext);
			scheduler.getContext().put("executorService", executorService);
			for (SchedulerJob schedulerJob : schedulerJobs) {
				JobDetail jobDetail = new JobDetail("job-" + index, null, schedulerJob.getJobClass());
				CronTrigger trigger = new CronTrigger("trigger-" + index, null, schedulerJob.getCronExpr());
				scheduler.scheduleJob(jobDetail, trigger);
				++index;
			}
			
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	public synchronized void startup() {
		try {
			scheduler.start();
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}
	
	public void shutdown() {
		try {
			scheduler.shutdown();
		} catch (SchedulerException e) {
			throw new RuntimeException(e);
		}
	}
	
}
